/**
 * SessionThreadPool.java $version 1.0 2010. 08. 12
 *
 * Copyright 2010 NHN Corp. All rights Reserved.
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.eltonkent.dashboard.service;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import com.eltonkent.dashboard.service.ServiceManagerImpl.ManagedServiceTask;

/**
 * 
 * An SessionThreadPool that executes each submitted task using one of possibly
 * several pooled threads, normally configured using Executors factory methods.
 * 
 * Thread pools address two different problems: they usually provide improved
 * performance when executing large numbers of asynchronous tasks, due to
 * reduced per-task invocation overhead, and they provide a means of bounding
 * and managing the resources, including threads, consumed when executing a
 * collection of tasks. Each ThreadPoolExecutor also maintains some basic
 * statistics, such as the number of completed tasks.
 * 
 * To be useful across a wide range of contexts, this class provides many
 * adjustable parameters and extensibility hooks. However, programmers are urged
 * to use the more convenient Executors factory methods
 * Executors.newCachedThreadPool() (unbounded thread pool, with automatic thread
 * reclamation), Executors.newFixedThreadPool(int) (fixed size thread pool) and
 * Executors.newSingleThreadExecutor() (single background thread), that
 * preconfigure settings for the most common usage scenarios. Otherwise, use the
 * following guide when manually configuring and tuning this class:
 * 
 * @see java.util.concurrent.ThreadPoolExecutor
 * 
 * @author Accenture India
 * 
 */
public class SessionThreadPool extends ThreadPoolExecutor {
	public static final int QUEUE_SIZE = 250;
	public static final int MAX_THREADS_COUNT = 2;

	private static final long serialVersionUID = 1L;
	private static LinkedBlockingQueue<Runnable> blockingQueue = new LinkedBlockingQueue<Runnable>(
			250);

	private static ThreadFactory threadFactory = new ThreadFactory() {

		private AtomicInteger atomicInteger = new AtomicInteger(1);

		@Override
		public Thread newThread(Runnable runnable) {
			String threadName = "SessionThread="
					+ atomicInteger.getAndIncrement();
			return new Thread(runnable, threadName);
		}
	};

	/**
	 * Creates a new SessionThreadPool with the initial parameters.
	 * 
	 * @see com.nhn.android.wingspoon.constant.MAX_THREADS_COUNT
	 * @see com.nhn.android.wingspoon.constant.MAX_THREADS_COUNT
	 */
	public SessionThreadPool() {
		super(MAX_THREADS_COUNT, MAX_THREADS_COUNT, 0L, TimeUnit.MILLISECONDS,
				blockingQueue, threadFactory);
	}

	/**
	 * Method invoked upon completion of execution of the given Runnable. This
	 * method is invoked by the thread that executed the task. If non-null, the
	 * Throwable is the uncaught exception that caused execution to terminate
	 * abruptly.
	 * 
	 * @param thread
	 *            - the thread that will run task r.
	 * @param runnable
	 *            - the task that will be executed.
	 */
	@Override
	protected void afterExecute(Runnable runnable, Throwable throwable) {
		ManagedServiceTask<?> serviceTask = (ManagedServiceTask<?>) runnable;
		serviceTask.postExecute();
	}

	/**
	 * Method invoked prior to executing the given Runnable in the given thread.
	 * This method is invoked by thread t that will execute task r, and may be
	 * used to re-initialize ThreadLocals, or to perform logging.
	 * 
	 * @param thread
	 *            - the thread that will run task r.
	 * @param runnable
	 *            - the task that will be executed.
	 */
	@Override
	protected void beforeExecute(Thread thread, Runnable runnable) {
		ManagedServiceTask<?> serviceTask = (ManagedServiceTask<?>) runnable;
		serviceTask.preExecute();
	}
}
